import axios from 'axios';
import {ElMessageBox, ElNotification} from 'element-plus';
import config from "@/config";
import tool from '@/utils/tool';
import router from '@/router';

axios.defaults.baseURL = ''

axios.defaults.timeout = config.TIMEOUT

// HTTP request 拦截器
axios.interceptors.request.use(
    (conf) => {
        let token = tool.data.get("APP_TOKEN");
        if (token) {
            conf.headers[config.TOKEN_NAME] = config.TOKEN_PREFIX + token
        }
        if (!config.REQUEST_CACHE && conf.method === 'get') {
            conf.params = conf.params || {};
            conf.params['_'] = new Date().getTime();
        }
        Object.assign(conf.headers, config.HEADERS)
        return conf;
    },
    (error) => {
        return Promise.reject(error);
    }
);

//FIX 多个API同时401时疯狂弹窗BUG
let MessageBox_401_show = false

// HTTP response 拦截器
axios.interceptors.response.use(
    (response) => {
        return response;
    },
    (error) => {
        if (error.response) {
            if (error.response.status === 404) {
                ElNotification.error({
                    title: '请求错误',
                    message: "Status:404，正在请求不存在的服务器资源"
                });
            } else if (error.response.status === 500) {
                ElNotification.error({
                    title: '请求错误',
                    message: error.response.data.message || "Status:500，服务器发生错误，请联系开发人员"
                });
            } else if (error.response.status === 401) {
                if (!MessageBox_401_show) {
                    MessageBox_401_show = true
                    ElMessageBox.confirm('当前用户已被登出或无权限访问当前资源，请尝试重新登录后再操作', '无权限访问', {
                        type: 'error',
                        closeOnClickModal: false,
                        center: true,
                        confirmButtonText: '重新登录',
                        beforeClose: (action, instance, done) => {
                            MessageBox_401_show = false
                            done()
                        }
                    }).then(() => {
                        router.replace({path: '/login'});
                    }).catch(() => {
                    })
                }
            } else {
                ElNotification.error({
                    title: '请求错误',
                    message: error.message || `Status:${error.response.status}，未知错误！`
                });
            }
        } else {
            ElNotification.error({
                title: '请求错误',
                message: "请求服务器无响应！"
            });
        }
        return Promise.reject(error.response);
    }
);

let http = {
    /** get 请求
     * @param  {string} url 接口地址
     * @param  {object} params 请求参数
     * @param  {object} config 参数
     */
    get: function (url, params = {}, config = {}) {
        return new Promise((resolve, reject) => {
            axios({
                method: 'get',
                url: url,
                params: params,
                ...config
            }).then((response) => {
                resolve(response.data);
            }).catch((error) => {
                reject(error);
            })
        })
    },

    /** post 请求
     * @param  {接口地址} url 接口地址
     * @param  {请求参数} data 请求参数
     * @param config
     * @param  {参数} data 请求参数
     */
    post: function (url, data = {}, config = {}) {
        return new Promise((resolve, reject) => {
            axios({
                method: 'post',
                url: url,
                data: data,
                ...config
            }).then((response) => {
                resolve(response.data);
            }).catch((error) => {
                reject(error);
            })
        })
    },

    /** put 请求
     * @param  {接口地址}  url 接口地址
     * @param  {请求参数}  data 请求参数
     * @param  {参数} config 参数
     */
    put: function (url, data = {}, config = {}) {
        return new Promise((resolve, reject) => {
            axios({
                method: 'put',
                url: url,
                data: data,
                ...config
            }).then((response) => {
                resolve(response.data);
            }).catch((error) => {
                reject(error);
            })
        })
    },

    /** patch 请求
     * @param  {接口地址} url 接口地址
     * @param  {请求参数}  data 请求参数
     * @param  {参数} config 参数
     */
    patch: function (url, data = {}, config = {}) {
        return new Promise((resolve, reject) => {
            axios({
                method: 'patch',
                url: url,
                data: data,
                ...config
            }).then((response) => {
                resolve(response.data);
            }).catch((error) => {
                reject(error);
            })
        })
    },

    /** delete 请求
     * @param  {接口地址} url 接口地址
     * @param  {请求参数}  data 请求参数
     * @param  {参数} config 参数
     */
    delete: function (url, data = {}, config = {}) {
        return new Promise((resolve, reject) => {
            axios({
                method: 'delete',
                url: url,
                data: data,
                ...config
            }).then((response) => {
                resolve(response.data);
            }).catch((error) => {
                reject(error);
            })
        })
    },

    /** jsonp 请求
     * @param  {接口地址} url 接口地址
     * @param  {JSONP回调函数名称} name JSONP回调函数名称
     */
    jsonp: function (url, name = 'jsonp') {
        return new Promise((resolve) => {
            let script = document.createElement('script')
            let _id = `jsonp${Math.ceil(Math.random() * 1000000)}`
            script.id = _id
            script.type = 'text/javascript'
            script.src = url
            window[name] = (response) => {
                resolve(response)
                document.getElementsByTagName('head')[0].removeChild(script)
                try {
                    delete window[name];
                } catch (e) {
                    window[name] = undefined;
                }
            }
            document.getElementsByTagName('head')[0].appendChild(script)
        })
    }
}

export default http;
